#include "RDB.h"
#include <chrono>

#define DEFAULT_PORT        48190   /* for image port it should be 48192 */
#define DEFAULT_BUFFER      204800


int main() {
    int clientSocket;
    struct sockaddr_in serverAddr;

    // 创建TCP套接字
    clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (clientSocket < 0) {
        std::cerr << "Error creating socket" << std::endl;
        return 1;
    }

    // 设置服务器地址和端口
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(DEFAULT_PORT); // 服务器端口号
    serverAddr.sin_addr.s_addr = inet_addr("192.168.1.135"); // 服务器IP地址

    // 连接到服务器
    if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
        std::cerr << "Error connecting to server" << std::endl;
        return 1;
    }

    std::cout << "Connected to server" << std::endl;

    char* szBuffer = new char[DEFAULT_BUFFER];  // allocate on heap
    unsigned int  bytesInBuffer = 0;
    size_t bufferSize = sizeof( RDB_MSG_HDR_t);
    unsigned char *pData = (unsigned char*) calloc(1, bufferSize);
    static bool sSendTrigger = false;//是否控主车标志位
    static bool sParseMessage = true;//是否解析信息
    static bool sParseMessageEntry = false;//是否解析信息包
    auto timeInterval = std::chrono::milliseconds(20);//20ms决策频率
    auto timeStart = std::chrono::steady_clock::now();
    RDB_MSG_NEED rdbMsgNeed;
    std::tuple<double, double, double> control;
    
    // 接收服务器的响应
    while (true) {
       int ret = recv(clientSocket, szBuffer, DEFAULT_BUFFER, 0);
       if (ret == -1) {
            std::cerr << "Error receiving data" << std::endl;
            break;
       }
       else if (ret == 0) {
            std::cerr << "Connection closed by server" << std::endl;
            break;
       }
       else {
            // do we have to grow the buffer??
            if ((bytesInBuffer + ret) > bufferSize) {
            pData = (unsigned char*) realloc(pData, bytesInBuffer + ret);
            bufferSize = bytesInBuffer + ret;
            }

            memcpy(pData + bytesInBuffer, szBuffer, ret);
            bytesInBuffer += ret;

            // already complete messagae?
            if (bytesInBuffer >= sizeof( RDB_MSG_HDR_t)) {
                RDB_MSG_HDR_t* hdr = (RDB_MSG_HDR_t*) pData;

                // is this message containing the valid magic number?
                if (hdr->magicNo != RDB_MAGIC_NO) {
                    std::cerr << "message receiving is out of sync; discarding data" << std::endl;
                    bytesInBuffer = 0;
                }

                while (bytesInBuffer >= (hdr->headerSize + hdr->dataSize)) {
                    unsigned int msgSize = hdr->headerSize + hdr->dataSize;
                    bool isImage = false;
                    
                    //定时改变sParseMessage，达到定时处理信息的目的
                    auto timeEnd = std::chrono::steady_clock::now();
                    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(timeEnd - timeStart);
                    if (duration >= timeInterval) {
                        sParseMessage = true;
                        timeStart = timeEnd;
                    }

                    // now parse the message    
                    if (sParseMessage) {
                        bool last_sParseMessageEntry = sParseMessageEntry;
                        parseRDBMessage((RDB_MSG_t*) pData, isImage, sParseMessageEntry, rdbMsgNeed);
                        // 获取交通信息后，决策代码于此书写
                        if (last_sParseMessageEntry == true && sParseMessageEntry == false) {
                            // 决策
                            control = decision(rdbMsgNeed);
                            rdbMsgNeed.clear();
                            sParseMessage = false;
                            // auto now = std::chrono::system_clock::now();
                            // std::cout << "当前时间：" << std::chrono::system_clock::to_time_t(now) << std::endl;
                            // std::cout << "一次完整的信息读取！！！！" << std::endl;
                        }

                    }

                    // trigger after image has been handled
                    if (sSendTrigger)
                        sendTrigger(clientSocket, ((RDB_MSG_t*) pData)->hdr.simTime, ((RDB_MSG_t*) pData )->hdr.frameNo);
                    
                    // remove message from queue
                    memmove(pData, pData + msgSize, bytesInBuffer - msgSize);
                    bytesInBuffer -= msgSize;
                    std::cout << "----------  消息减一  ----------" << std::endl;
                }
            }
       }
       std::cout << "----------  数据包加一  ----------" << std::endl;
    }

    // 关闭套接字
    close(clientSocket);

    return 0;
}